package hc.j2me;

import hc.core.ConditionWatcher;
import hc.core.ContextManager;
import hc.core.IConstant;
import hc.core.IContext;
import hc.core.IWatcher;
import hc.core.L;
import hc.core.RootConfig;
import hc.core.util.ByteUtil;
import hc.core.util.ILog;
import hc.core.util.LocationProvider;
import hc.core.util.LogManager;
import hc.core.util.MsgNotifier;
import hc.core.util.StringUtil;
import hc.j2me.ui.LoginForm;
import hc.j2me.ui.RSConfig;
import hc.j2me.ui.UIManager;
import hc.j2me.util.ImageUtility;
import hc.j2me.util.J2MEHttpUtil;
import hc.j2me.util.Jcip;
import hc.j2me.util.LineInputStream;
import hc.j2me.util.ScreenUtil;
import hc.j2me.util.SoundUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

public class Starter {
	public static final String RS_CONFIG_NAME = "config";
	public static final int RMS_CONFIG_NO = 1;
	public static boolean isServerLineOff = false;
	public Starter() {
		// 检查是否为新安装，需要初始化
		RecordStore rs = null;
		try {
			rs = RecordStore.openRecordStore(RS_CONFIG_NAME, false);
			if (rs != null) {
				byte[] bs = rs.getRecord(RMS_CONFIG_NO);
				if(bs != null){
					isInited = true;
				}
			}
		} catch (Throwable e) {
		}finally{
			try{
				rs.closeRecordStore();
			}catch (Throwable e) {
			}
		}
		
		if(isInited == false){
			final Starter self = this;
			final Form serviceForm = new Form("Important");
			
			serviceForm.append("Using services may involve transmitting large amounts of data " +
					"through your service provider's network.\n" +
					" \n" +
					"Your first consideration while using services in traffic has to be safety.\n" +
					" \n" +
					"All services maybe occasionally unavailable.");
			final IWatcher getFirstSC = new IWatcher() {
				String[] urls;
				int i = 0;
				public boolean watch() {
					for (; i < urls.length; i++) {
						final Image img = ScreenUtil.loadImage(urls[i]);
						if(img == null){
							return false;
						}
						firstImg[i] = img;
					}
					return true;
				}
				
				public void setPara(Object p) {
					this.urls = (String[])p;
				}
				
				public boolean isNotCancelable() {
					return false;
				}
				
				public void cancel() {
				}
			};

			ConditionWatcher.addWatcher(new IWatcher() {
				public boolean watch() {
					//不能调用ForSimu，因为没有初始化
					String content = null;
					int count = 0;
					while(true){
						content = J2MEHttpUtil.getAjax("http://homecenter.mobi/ajax/mobi_sc.php");
						if(content != null || count++ > 2){
							break;
						}
						try{
							Thread.sleep(1200);
						}catch (Exception e) {
							
						}
					}
					if(content != null){
						Vector v = StringUtil.split(content, "###");
						
						int sc_width = Integer.parseInt((String)v.elementAt(v.size() - 2));
						int sc_height = Integer.parseInt((String)v.elementAt(v.size() - 1));
						
						//横屏符合尺寸
						boolean isFitScreen = false;
						if(Main.gameWidth >= sc_width && Main.gameHeight >= sc_height){
							isFitScreen = true;
						}
						if(isFitScreen || (Main.gameWidth >= sc_height && Main.gameHeight >= sc_width)){
							scs = v;
							final int size = scs.size() - 2;
							firstImg = new Image[size];
							final String[] urls = new String[size];
							for (int i = 0; i < size; i++) {
								String url = (String)scs.elementAt(i);
								if(isFitScreen == false){
									final int endlen = url.indexOf(".png");
									url = url.substring(0, endlen) + "_w.png";
								}
								urls[i] = url;
							}
							getFirstSC.setPara(urls);
							ConditionWatcher.addWatcher(getFirstSC);
						}
					}
					return true;
				}
				
				public void setPara(Object p) {
				}
				
				public boolean isNotCancelable() {
					return false;
				}
				
				public void cancel() {
				}
			});
			
			StringItem item = new StringItem("", "O K", Item.BUTTON);
			//不能使用cmd_ok变量，因为它的getUIString会初始化config.userLang
			item.setDefaultCommand(new Command("O K", Command.OK, 1));
			item.setItemCommandListener(new ItemCommandListener() {
				public void commandAction(Command c, Item item) {
					if(scs != null){
						if(firstImg[0] != null){
							//先装载第一个图片
							UIManager.pushInAndSwithToNew(new ScreenShotCanvas(self, false, getFirstSC));
						}
					}else{
						//一直等待到获得数据
						//init();
					}
				}
			});
			serviceForm.append(item);
			UIManager.pushInAndSwithToNew(serviceForm);
		}else{
			init(false);
		}
	}

	static Vector scs;
	static Image[] firstImg;
	boolean isInited = false;
	void init(boolean isFirstRun) {
		
		if (isInited == false) {
			initSys();
		}
		// 加载初始参数，如语言等
		loadIni(RS_CONFIG_NAME);

		// 注意：以上步骤要加载于IConstant.setInstance之前，因为后者依赖于参数初始化
		//LogManager.setLog(new J2MERMSLog());
		LogManager.setLog(new J2MELog());

		if(properties.get("_testSimu") != null){
			L.enable(true);
		}else{
			L.enable(false);
		}

		J2MEConstant constant = new J2MEConstant();

		IConstant.setInstance(constant);

		cmd_ok = new Command(getUIString(ScreenUtil.OK), Command.OK, 1);
		cmd_cancel = new Command(getUIString(ScreenUtil.CANCEL), Command.CANCEL, 1);

		BACK_COMMAND = new Command(getUIString(ScreenUtil.BACK), Command.BACK, 0);
		EXIT_COMMAND = new Command(getUIString(ScreenUtil.EXIT), Command.EXIT, 0);

		final RootConfig rc = RootConfig.getInstance();
		if(rc == null){
			final Form staringForm = new StartForm(Starter.getUIString("1"));
			
			staringForm.append(Starter.getUIString("1000"));
			staringForm.append("Please retry after few minutes." + "\n");
			
			StringItem item = new StringItem("", Starter.getUIString(ScreenUtil.EXIT), Item.BUTTON);
			item.setDefaultCommand(EXIT_COMMAND);
			item.setItemCommandListener((ItemCommandListener)staringForm);
			
			staringForm.append(item);
			
			UIManager.pushInAndSwithToNew(staringForm);
		}else{
			if(config.colorBit == 0){
				//从服务器配置中获得初始值
				config.colorBit = RootConfig.getInstance().getIntProperty(RootConfig.p_mobile_color_bit_install);
			}
			
			String midpVer = Main.getMidletVer();
			String cfgVer = rc.getProperty(RootConfig.p_MIDP_VER);
			if (StringUtil.higer(cfgVer, midpVer)) {
				startUpgrade();
			}else{
				loginProcess(isFirstRun);
			}
		}
	}

	private void loginProcess(boolean isFirst) {
		UIManager.emptyStack();

		Starter.config.width = Main.gameWidth;
		Starter.config.height = Main.gameHeight;
		
		Starter.config.isTouchScreen = Main.isTouchScreen;

//			System.out.println("Screen Width:" + ScreenClientManager.getClientWidth());
//			System.out.println("Screen Height:" + ScreenClientManager.getClientHeight());
		Starter.update(Starter.config);

		ScreenClientManager.setClientWH(Starter.config.width, Starter.config.height);
		ScreenClientManager.setTouchScreen(Starter.config.isTouchScreen);
		ScreenClientManager.setClientLang(Starter.config.userLang);

		Object obj = LocationProvider.getInstance();
		if (obj != null && (Starter.config.isSupportGPS == false)) {
			// 未来可能加载GPS模块
			Starter.config.isSupportGPS = true;
			ScreenClientManager.setSupportGPS(true);
			Starter.update(Starter.config);
		} else if (obj == null && Starter.config.isSupportGPS) {
			// 未来可能移除GPS模块
			Starter.config.isSupportGPS = false;
			ScreenClientManager.setSupportGPS(false);
			Starter.update(Starter.config);
		}

		UIManager.pushInAndSwithToNew(new LoginForm(isFirst));
	}

	public void startUpgrade() {
		final IWatcher ok_action = new IWatcher() {
			public boolean watch() {
				try {
					Main.main.platformRequest("http://homecenter.mobi/download/hcME.jad");
					Main.main.destroyApp(true);
					Main.main.notifyDestroyed();
				} catch (Exception e) {

				}
				return false;
			}
			
			public void setPara(Object p) {
			}

			public void cancel() {
			}

			public boolean isNotCancelable() {
				return false;
			}
		};
		final IWatcher cancle_action = new IWatcher() {
			public boolean watch() {
				loginProcess(false);

				return false;
			}
			
			public void setPara(Object p) {
			}

			public void cancel() {
			}

			public boolean isNotCancelable() {
				return false;
			}
		};
		String msg = getUIString("m10");
		
		msg += "\n\n" + "Before upgrade:\n\n" +
				"1. in outdoor, try older ver, if error in connect, " +
				"then upgrade to newer (keep old data in upgrading)." +
				"\n\n" +
				"2. in home, upgrade now, if error in connect, " +
				"then restart App server to auto upgrade PC side." +
				"\n\n" +
				"3. Do NOT upgrade if config user encryptor.";
		//升级增加ID提示
//		if(Starter.config.uuid.length() > 0){
//			msg += "\n\n" + "My ID : " + Starter.config.uuid;
//		}
		comfirm(getUIString(ScreenUtil.INFO), msg , ok_action, cancle_action);
	}

	public static void comfirm(String title, String msg, final IWatcher ok_action, final IWatcher cancle_action) {
		javax.microedition.lcdui.Form form = new javax.microedition.lcdui.Form(title);
		form.addCommand(cmd_ok);
		form.addCommand(cmd_cancel);
		form.setCommandListener(new CommandListener() {
			public void commandAction(Command arg0, Displayable arg1) {
				if(arg0 == cmd_ok){
					ok_action.watch();
				}else if(arg0 == cmd_cancel){
					cancle_action.watch();
				}
			}});
		form.append(msg);

		UIManager.pushInAndSwithToNew(form);
	}

	public static RSConfig config = null;

	/**
	 * 检测当前语言等
	 */
	private void initSys() {
		// 获得当前用户语言
		config = new RSConfig();
		config.userLang = RSConfig.getSysLocale();

		writeNew(config);
	}

	private void loadIni(String file) {
		config = load(file);
		if (config == null) {
			config = new RSConfig();
			config.userLang = RSConfig.getSysLocale();
		}

		try {
			properties = new Hashtable();

			InputStream is = Main.main.getClass().getResourceAsStream(
					"/hc/hc_config.properties");
			Reader stream = new InputStreamReader(is, "ISO-8859-1");
			
			load(stream, properties);
		} catch (Exception e) {

		}

	}

	public static int getIconSize(final int width, final int height) {
		if(width >= 280 && height >= 280){
			ImageUtility.sp_bound = 10;
			return 32;
		}else{
			return 16;			
		}
	}

	public static void displayAlert(String caption, String text, int type,
			Object imageData, int timeOut) {
		AlertType at = null;
		if (type == IContext.CONFIRMATION) {
			at = AlertType.CONFIRMATION;
		} else if (type == IContext.INFO) {
			at = AlertType.INFO;
		} else if (type == IContext.ERROR) {
			at = AlertType.ERROR;
		} else if (type == IContext.WARN) {
			at = AlertType.WARNING;
		} else if (type == IContext.ALARM) {
			at = AlertType.ALARM;
		} else {
			at = AlertType.INFO;
		}

		Alert alert = new Alert(caption);
	
		alert.setTitle(caption);
		alert.setString(text);
		alert.setType(at);
		if (timeOut == 0) {
			alert.setTimeout(Alert.FOREVER);
		} else {
			alert.setTimeout(timeOut);
		}

		if (imageData != null) {
			Image image = Jcip.decodeBase64ToImage((String) imageData);
			alert.setImage(image);
		}

		// 不能采用入栈
		UIManager.dispAlert(alert);
	}

	public static byte[] ser(RSConfig cfg) {
		String ver = Main.getMidletVer();
		boolean isHigh = StringUtil.higer(ver, "5.37");
		
		byte[] bs = null;
		try {
			// Creates a new data output stream to write data
			// to the specified underlying output stream
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			DataOutputStream dos = new DataOutputStream(baos);
			
			if(isHigh){
				//High版本标识
				dos.writeByte(0);
				dos.writeByte(0);
			}
			
			writeNewUTF8(dos, isHigh, cfg.userLang);
			dos.writeBoolean(cfg.isHideToolbar);
			dos.writeBoolean(cfg.isMute);
			dos.writeInt(cfg.colorBit);
			dos.writeInt(cfg.refreshMS);
			writeNewUTF8(dos, isHigh, cfg.certKey);
			writeNewUTF8(dos, isHigh, cfg.stunAndPort);
			dos.writeInt(cfg.width);
			dos.writeInt(cfg.height);
			dos.writeBoolean(cfg.isTouchScreen);
			dos.writeBoolean(cfg.isSupportGPS);
			writeNewUTF8(dos, isHigh, cfg.uuid);
			dos.writeInt(cfg.toneStep);
			dos.writeInt(cfg.auStep);
			dos.writeInt(cfg.failAlphaMax);
			dos.writeInt(cfg.passAlphaMin);
			dos.writeBoolean(cfg.isUseAlpha);
			dos.writeBoolean(cfg.isStorePass);
			writeNewUTF8(dos, isHigh, cfg.password);
			dos.writeBoolean(cfg.isTCPOnly);
			
			bs = baos.toByteArray();
			
			baos.close();
			dos.close();
		} catch (Exception e) {
		}
		return bs;
	}

	/**
	 * 将传入的byte 类型数据反序列化为已知数据结构
	 */
	public static RSConfig deser(byte[] data) {
		boolean isHigh = false;
		if(data[0] == 0 && data[1] == 0){
			//High版本标识
			isHigh = true;
		}
		
		RSConfig word = null;
		ByteArrayInputStream bais = null;
		DataInputStream dis = null;
		try {
			bais = new ByteArrayInputStream(data);
			dis = new DataInputStream(bais);
			word = new RSConfig();
			
			if(isHigh){
				//丢掉前面的High版本标识
				dis.readByte();
				dis.readByte();
			}
			
			word.userLang = readNewUTF8(dis, isHigh);
			word.isHideToolbar = dis.readBoolean();
			word.isMute = dis.readBoolean();
			word.colorBit = dis.readInt();
			word.refreshMS = dis.readInt();
			word.certKey = readNewUTF8(dis, isHigh);
			word.stunAndPort = readNewUTF8(dis, isHigh);
			word.width = dis.readInt();
			word.height = dis.readInt();
			word.isTouchScreen = dis.readBoolean();
			word.isSupportGPS = dis.readBoolean();
			word.uuid = readNewUTF8(dis, isHigh);
			word.toneStep = dis.readInt();
			word.auStep = dis.readInt();
			word.failAlphaMax = dis.readInt();
			word.passAlphaMin = dis.readInt();
			word.isUseAlpha = dis.readBoolean();
			word.isStorePass = dis.readBoolean();
			word.password = readNewUTF8(dis, isHigh);
			word.isTCPOnly = dis.readBoolean();
			word.isTCPOnly = dis.readBoolean();
			
			bais.close();
			dis.close();
		} catch (Throwable e) {
			try {
				bais.close();
				dis.close();
			} catch (Throwable ee) {
			}
		}
		return word;
	}
	
	private static void writeNewUTF8(final DataOutputStream dos, final boolean isHigh, final String str) throws Exception{
		if(isHigh){
			final byte[] bs = str.getBytes(IConstant.UTF_8);
			dos.writeInt(bs.length);
			dos.write(bs);
		}else{
			dos.writeUTF(str);
		}
	}
	
	private static String readNewUTF8(final DataInputStream dis, final boolean isHigh) throws Exception{
		if(isHigh){
			final int len = dis.readInt();
			final byte[] bs = ByteUtil.byteArrayCacher.getFree(len);

			dis.read(bs, 0, len);
			String out = new String(bs, 0, len, IConstant.UTF_8);
			
			ByteUtil.byteArrayCacher.cycle(bs);
			return out;
		}else{
			return dis.readUTF();
		}
	}

	public static RSConfig load(String file) {
		RecordStore rs;
		try {
			rs = RecordStore.openRecordStore(file, true);
			byte[] bs = rs.getRecord(RMS_CONFIG_NO);
			RSConfig cfg = deser(bs);
			rs.closeRecordStore();
			return cfg;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void update(RSConfig cfg) {
		RecordStore rs;
		try {
			rs = RecordStore.openRecordStore(RS_CONFIG_NAME, true);
			byte[] bs = ser(cfg);
			rs.setRecord(RMS_CONFIG_NO, bs, 0, bs.length);
			rs.closeRecordStore();
		} catch (RecordStoreException e) {
			e.printStackTrace();
		}
	}

	public static void writeNew(RSConfig cfg) {
		RecordStore rs;
		try {
			rs = RecordStore.openRecordStore(RS_CONFIG_NAME, true);
			byte[] bs = ser(cfg);
			rs.addRecord(bs, 0, bs.length);
			rs.closeRecordStore();

			// String[] ls = RecordStore.listRecordStores();
			// for (int i = 0; i < ls.length; i++) {
			// System.out.println(ls[i]);
			// }
		} catch (RecordStoreException e) {
			e.printStackTrace();
		}
	}

	public static void soundOK() {
		SoundUtil.playTone(80, 500, 40);
	}

	public static void soundFail() {
		SoundUtil.playTone(40, 500, 50);
	}
	
	public static Hashtable properties;
	private static Hashtable resources;

	/**
	 * 最长不超过1024char
	 * 
	 * @param prop
	 * @return
	 */
	public static String getUIString(String prop) {
		String out;
		if (resources != null) {
			out = (String) resources.get(prop);
			return (out == null)?"":out;
		}

		resources = new Hashtable();

		InputStream is = null;
		Class MAIN_CLASS = Main.main.getClass();

		try {
			// System.out.println("lang:" + config.userLang);
			L.V = L.O ? false : LogManager.log("Lang:" + config.userLang);
			is = MAIN_CLASS.getResourceAsStream("/hc/j2me/res/"
					+ config.userLang + ".properties");
		} catch (Exception e) {
		}
		if(is == null){
			try {
				is = MAIN_CLASS.getResourceAsStream("/hc/j2me/res/"
						+ config.userLang.substring(0, 2) + ".properties");
			} catch (Exception e) {
			}
			if(is == null){
				is = MAIN_CLASS.getResourceAsStream("/hc/j2me/res/en-US.properties");
			}
		}
		Reader stream = null;
		try {
			stream = new InputStreamReader(is, "ISO-8859-1");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		load(stream, resources);
		
		out = (String) resources.get(prop);
		return (out == null)?"":out;
	}

	public static void load(Reader stream, Hashtable table) {
		LineInputStream line = new LineInputStream(stream);
		char[] Buf = new char[1024];
		int limit;
		int keyLen;
		int start;
		char c;
		boolean hasSep;
		boolean backslash;

		try {
			while ((limit = line.readLine()) >= 0) {
				c = 0;
				keyLen = 0;
				start = limit;
				hasSep = false;

				backslash = false;
				while (keyLen < limit) {
					c = line.lineBuf[keyLen];
					// need check if escaped.
					if ((c == '=' || c == ':') && !backslash) {
						start = keyLen + 1;
						hasSep = true;
						break;
					} else if ((c == ' ' || c == '\t' || c == '\f')
							&& !backslash) {
						start = keyLen + 1;
						break;
					}
					if (c == '\\') {
						backslash = !backslash;
					} else {
						backslash = false;
					}
					keyLen++;
				}
				while (start < limit) {
					c = line.lineBuf[start];
					if (c != ' ' && c != '\t' && c != '\f') {
						if (!hasSep && (c == '=' || c == ':')) {
							hasSep = true;
						} else {
							break;
						}
					}
					start++;
				}
				String key = loadConvert(line.lineBuf, 0, keyLen, Buf);
				String value = loadConvert(line.lineBuf, start, limit - start, Buf);
				
				table.put(key, value);
			}
		} catch (Exception e) {

		}finally{
			try {
				stream.close();
			} catch (Exception e) {
			}
		}
	}

	private static String loadConvert(char[] in, int off, int len,
			char[] convtBuf) {
		if (convtBuf.length < len) {
			int newLen = len * 2;
			convtBuf = new char[newLen];
		}
		char aChar;
		char[] out = convtBuf;
		int outLen = 0;
		int end = off + len;

		while (off < end) {
			aChar = in[off++];
			if (aChar == '\\') {
				aChar = in[off++];
				if (aChar == 'u') {
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = in[off++];
						switch (aChar) {
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							value = (value << 4) + aChar - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							value = (value << 4) + 10 + aChar - 'a';
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							value = (value << 4) + 10 + aChar - 'A';
							break;
						default:
							throw new IllegalArgumentException("Error encoding.");
						}
					}
					out[outLen++] = (char) value;
				} else {
					if (aChar == 't')
						aChar = '\t';
					else if (aChar == 'f')
						aChar = '\f';
					else if (aChar == 'r')
						aChar = '\r';
					else if (aChar == 'n')
						aChar = '\n';
					out[outLen++] = aChar;
				}
			} else {
				out[outLen++] = aChar;
			}
		}
		return new String(out, 0, outLen);
	}

	// 注意：要置于最后，因为依赖其它数据
	public static Command BACK_COMMAND, EXIT_COMMAND;

	// 确定并退出, 不能用Command.back，可以用Command.Exit
	public static Command cmd_ok, cmd_cancel;
	
	private static CommandListener OK_NOBIZ_CMD_LISTENER;
	
	public static CommandListener getOK_NOBIZ_LISTENER(){
		if(OK_NOBIZ_CMD_LISTENER == null){
			OK_NOBIZ_CMD_LISTENER = new CommandListener() {
				public void commandAction(Command c, Displayable d) {
					if(c == cmd_ok){
						UIManager.exitOrReturn();
					}
				}
			};
		}
		return OK_NOBIZ_CMD_LISTENER;
	}
}


class J2MELog implements ILog {	
	final Calendar c;
	
	J2MELog(){
		c = Calendar.getInstance();
	}
	
	public void errWithTip(String msg) {
		ContextManager.displayMessage(Starter.getUIString(ScreenUtil.ERROR),
				msg, IContext.ERROR, 0);
	}

	public void err(String msg) {
		
	}
	
	public void exit() {
	}

	public void log(String msg) {
		c.setTime(new Date());

		System.out.println(c.get(Calendar.HOUR_OF_DAY) + ":" +c.get(Calendar.MINUTE)
			     + ":" + c.get(Calendar.SECOND) + "." + c.get(Calendar.MILLISECOND) + " " + msg);
	}

	public void info(String msg) {
		MsgNotifier.getInstance().notifyNewMsg(msg);
	}

	public void flush() {
	}
};

class StartForm extends Form implements ItemCommandListener {

	public StartForm(String title) {
		super(title);
	}

	public void commandAction(Command c, Item item) {
		Main.notifyExit();
	}
	
}
class ScreenShotCanvas extends GameCanvas{
	private Starter starter;
	private int currIdx = 0;
	Object[] toGetImage = new Object[2];
	IWatcher watcher;
	protected ScreenShotCanvas(Starter starter, boolean suppressKeyEvents, IWatcher watcher) {
		super(suppressKeyEvents);
		setFullScreenMode(true);
		this.starter = starter;
		this.watcher = watcher;
		
		try{
			pre = Image.createImage("/hc/j2me/res/sc_pre.png");
			next = Image.createImage("/hc/j2me/res/sc_next.png");
			exit = Image.createImage("/hc/j2me/res/sc_exit.png");
			step = Image.createImage("/hc/j2me/res/sc_step.png");
			cur_step = Image.createImage("/hc/j2me/res/sc_step_c.png");
		}catch (Exception e) {
		}
	}
	
	Image pre, next, exit, step, cur_step;
	final int gameWidth = Main.gameWidth;
	final int gameHeight = Main.gameHeight;
	
	private void afterShowScreenShot(){
		Starter.firstImg = null;
		Starter.scs = null;
		starter.init(true);
	}
	
	public void pointerReleased(final int x, final int y) {
		if(x > (gameWidth - exit.getWidth()) && y < (exit.getHeight())){
			afterShowScreenShot();
			return;
		}else if(currIdx > 0 && (y > (gameHeight - pre.getHeight())) && x < pre.getWidth()){
			currIdx--;
			repaint();
			return;
		}else if(y > (gameHeight - next.getHeight()) && x > (gameWidth - next.getWidth())){
			if(currIdx == (Starter.firstImg.length - 1)){
				afterShowScreenShot();
				return;
			}else{
				if(Starter.firstImg[currIdx + 1] != null){
					currIdx++;
					repaint();
					return;
				}
			}
		}
	}

	public void paint(Graphics g) {
		g.setColor(255, 255, 255);
		g.fillRect(0, 0, gameWidth, gameHeight);
		
		g.drawImage(Starter.firstImg[currIdx], gameWidth/2, gameHeight/2, Graphics.HCENTER|Graphics.VCENTER);
		
		g.drawImage(exit, gameWidth, 0, Graphics.RIGHT|Graphics.TOP);
		if(currIdx != 0){
			g.drawImage(pre, 0, gameHeight, Graphics.LEFT|Graphics.BOTTOM);
		}
		g.drawImage(next, gameWidth, gameHeight, Graphics.RIGHT|Graphics.BOTTOM);
		
		final int width_step = step.getWidth() + 5;
		final int step_height = gameHeight - next.getHeight() - 30;
		for (int startIdx = gameWidth - width_step * Starter.firstImg.length, i = 0; i < Starter.firstImg.length; i++) {
			g.drawImage(step, startIdx, step_height, Graphics.LEFT|Graphics.TOP);
			if(i == currIdx){
				g.drawImage(cur_step, startIdx, step_height, Graphics.LEFT|Graphics.TOP);
			}
			startIdx += width_step;
		}
	}
}